// Thud - a dynamic object-oriented language
// Copyright (C) 2009,2010 David H. Hovemeyer <david.hovemeyer@gmail.com>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

/*
 * CommandLine.cpp
 *
 *  Created on: Jan 3, 2010
 *      Author: dhovemey
 */

#include "util/String.h"
#include "util/CommandLine.h"

CommandLineException::CommandLineException(const std::wstring &msg)
	: Exception(msg)
{

}

CommandLineException::CommandLineException(const CommandLineException &other)
	: Exception(other)
{

}

CommandLineException::~CommandLineException()
{

}

CommandLine::CommandLine()
{

}


CommandLine::CommandLine(const char *format)
{
	const char *p = format;

	while (*p != '\0') {
		std::string opt("-");
		opt += *p;

		bool hasArg = false;
		if (*(p + 1) != '\0' && *(p + 1) == ':') {
			p++;
			hasArg = true;
		}

		if (hasArg) {
			addOption(opt);
		} else {
			addSwitch(opt);
		}

		p++;
	}
}

CommandLine::~CommandLine()
{

}

void CommandLine::parse(int &argc, char **&argv)
{
	// save the program name
	if (argv[0] == 0) {
		throw Exception(L"argv[0] is null");
	}
	m_progName = std::string(argv[0]);

	// parse options
	int i = 1;
	while (i < argc) {
		if (argv[i] == 0) {
			throw new Exception(L"Uh oh");
		}
		std::string opt(argv[i]);

		if (opt.size() == 0 || opt[0] != '-') {
			break;
		}

		OptionMap::iterator j = m_optionMap.find(opt);
		if (j == m_optionMap.end()) {
			throw CommandLineException(L"Unrecognized option: " + String::fromUtf8(opt));
		}

		bool requiresArg = (*j).second;

		if (requiresArg) {
			i++;
			if (i >= argc) {
				throw CommandLineException(String::fromUtf8(opt) + L" option requires argument");
			}
			if (argv[i] == 0) throw Exception(L"Yop");
			std::string arg(argv[i]);
			handleOption(opt, arg);
		} else {
			handleSwitch(opt);
		}

		i++;
	}

	// update argc/argv to reflect the options that were consumed
	argc = (argc - i);
	argv = &argv[i];
}

